package com.pn.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.pn.dto.AssignRoleDto;
import com.pn.entity.Auth;
import com.pn.entity.User;
import com.pn.entity.UserPageList;
import com.pn.entity.UserRole;
import com.pn.exception.DeleteUserException;
import com.pn.exception.UserExistsException;
import com.pn.mapper.RoleMapper;
import com.pn.mapper.UserMapper;
import com.pn.service.UserService;
import com.pn.utils.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    //根据用户名查找用户的业务方法
    @Override
    public User findUserByCode(String userCode) {
        return userMapper.findUserByCode(userCode);
    }


    //查询用户菜单树的业务方法
    //向redis缓存用户菜单树 -- 键是autoTree:userId  值是菜单树List<Auth>串
    @Override
    public List<Auth> autoTreeByUid(Integer userId) {
        //先查看redis中有没有存储菜单树
        String authTreeJson = stringRedisTemplate.opsForValue().get("authTree:" + userId);
        if (StringUtils.hasText(authTreeJson)){//判断authTreeJson有没有值
            //将菜单树List<Auth> 转的JSON串 转回菜单树List<Auth>并返回
            List<Auth> authTreeList = JSON.parseArray(authTreeJson, Auth.class);
            return authTreeList;
        }
        //redis中没有存储菜单树则进行以下操作
        //查询用户权限下的所有菜单
        List<Auth> allAuthList = userMapper.findAuthByUid(userId);
        //将所有的菜单List<Auth> 转成菜单树List<Auth>
        List<Auth> authTreeList = allAuthToAuthTree(allAuthList,0);
        //向redis中缓存菜单树
        String s = JSON.toJSONString(authTreeList);
        stringRedisTemplate.opsForValue().set("authTree:"+userId,s);
        return authTreeList;
    }

    public static List<Auth> allAuthToAuthTree(List<Auth> allAuthList,Integer pid){
        //拿到所有一级菜单
        List<Auth> firstLevelAuthList = new ArrayList<>();
        for (Auth auth : allAuthList) {
            if (auth.getParentId() == pid){
                firstLevelAuthList.add(auth);
            }
        }

        //再一级菜单的基础上遍历二级菜单，放入的是一级菜单的ChildAuth的中
        for (Auth firstAuth : firstLevelAuthList) {
            List<Auth> auths = allAuthToAuthTree(allAuthList, firstAuth.getAuthId());
            firstAuth.setChildAuth(auths);
        }
        return firstLevelAuthList;
    }

    //用户分页查询
    @Override
    public PageBean<User> userList(UserPageList userPageList) {
        PageHelper.startPage(userPageList.getPageNum(),userPageList.getPageSize());

        Page<User> page = userMapper.userList(userPageList);

        List<User> result = page.getResult();
        return new PageBean(page.getTotal(),result);
    }

    //添加用户
    @Override
    public void addUser(User user) {
        User userByCode = userMapper.findUserByCode(user.getUserCode());
        if(userByCode != null){
            throw new UserExistsException("用户名已存在");
        }

        Map<String,Object> map =(Map<String, Object>) ThreadLocalUtil.get();
        Integer userId =(Integer) map.get("userId");
        user.setUserState("0");
        user.setIsDelete("0");
        user.setCreateBy(userId);
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateBy(userId);
        user.setUpdateTime(LocalDateTime.now());
        user.setUserPwd(DigestUtil.hmacSign(user.getUserPwd()));

        userMapper.addUser(user);
    }

    //用户的启用禁用
    @Override
    public int updateState(User user) {
        if (user.getUserCode().equals("admin")){
            return 0;
        }

        int i = userMapper.updateState(user);
        return i;
    }

    @Autowired
    private RoleMapper roleMapper;
    //给用户分配角色的业务方法
    @Transactional
    @Override
    public void assignRole(AssignRoleDto assignRoleDto) {
        //先删除用户关联的角色
        roleMapper.removeUserRoleByUid(assignRoleDto.getUserId());
        //遍历前端勾选的角色名
        List<String> roleNameList = assignRoleDto.getRoleCheckList();
        for (String roleName : roleNameList) {
            //根据角色名字拿到角色id
            Integer roleId = roleMapper.findRoleIdByName(roleName);
            //根据用户id和角色id添加用户角色关联表
            UserRole userRole = new UserRole();
            userRole.setRoleId(roleId);
            userRole.setUserId(assignRoleDto.getUserId());
            roleMapper.insertUserRole(userRole);
        }
    }

    //删除用户的业务方法
    @Transactional
    @Override
    public Result deleteUserByIds(List<Integer> userIds) {
        for (Integer userid : userIds) {
            if(userid == 1){
                throw new DeleteUserException("超级管理员不能删除");
            }
        }

        int i = userMapper.setIsDeleteByUids(userIds);
        //根据用户ids修改用户为删除状态的方法
        roleMapper.romeveUserRoleByUid(userIds);
        if (i>0){
            return Result.ok("用户删除成功！");
        }
        return Result.err(Result.CODE_ERR_BUSINESS,"用户删除失败！");
    }

    //修改用户
    @Override
    public Result updateUserByUid(User user) {
        Map<String,Object> map =(Map<String,Object>) ThreadLocalUtil.get();
        Integer userId =(Integer) map.get("userId");
        user.setUpdateBy(userId);
        user.setUpdateTime(LocalDateTime.now());

        int i = userMapper.updateUserByUid(user);
        if (i > 0){
            return Result.ok("用户修改成功");
        }
        return Result.err(Result.CODE_ERR_BUSINESS,"用户修改失败");
    }

    //重置密码
    @Override
    public Result updatePwdByUid(Integer userId) {
        String pwd = DigestUtil.hmacSign(WarehouseConstants.USER_PWd);
        int i = userMapper.updatePwdByUid(userId,pwd);
        if (i > 0){
            return Result.ok("用户重置密码成功");
        }
        return Result.err(Result.CODE_ERR_BUSINESS,"用户重置密码失败");
    }
}
